/**
 * @file sr04.c
 * @brief 超声波传感器
 *
 * @author 钟涛
 *
 * @date 2022-05-09
 *
 * @copyright 海南大学 - 追光者
 */

#include <rtthread.h>
#include <rtdevice.h>
#include "drv_common.h"
#include "app_main.h"
#include "hw_delay.h"
#include "sr04.h"

#define DBG_TAG "sr04"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>

extern TIM_HandleTypeDef htim2;

/**
  * @brief TIM2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM2_Init(void)
{

  /* USER CODE BEGIN TIM2_Init 0 */

  /* USER CODE END TIM2_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM2_Init 1 */

  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 83;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 4294967295;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */

  /* USER CODE END TIM2_Init 2 */

}

///**
// * 硬件微秒延时
// * @param us 微秒数，范围1~65535。
// */
//void delay_us(uint32_t us)
//{
//    __HAL_TIM_SET_COUNTER(&htim2, 0);
//    HAL_TIM_Base_Start(&htim2);
//    while (__HAL_TIM_GET_COUNTER(&htim2) < us)
//        ;
//    HAL_TIM_Base_Stop(&htim2);
//}

/**
 * 读取距离
 * @return 距离（厘米）
 */
int sr04_read(rt_base_t trig_pin, rt_base_t echo_pin)
{
    int errCount = 0;

    HAL_TIM_Base_Stop(&htim2);
    //触发信号
    rt_pin_write(trig_pin, PIN_HIGH);
    hw_delay_us(40);
    rt_pin_write(trig_pin, PIN_LOW);

    while (rt_pin_read(echo_pin) == PIN_LOW)
    {
        hw_delay_us(10);
        if (errCount++ > 500)
        {
            return 413;
        }
    }
    __HAL_TIM_SET_COUNTER(&htim2, 0);
    HAL_TIM_Base_Start(&htim2);
    while (rt_pin_read(echo_pin) == PIN_HIGH)
    {
        hw_delay_us(1);
        if (errCount++ > 24000)
        {
            return 413;
        }
    }
    int us = __HAL_TIM_GET_COUNTER(&htim2) * 2;
    LOG_D("us: %d", us);
    HAL_TIM_Base_Stop(&htim2);

    return us / 58;
}

/**
 * 测量距离
 * @param num 模块编号
 * @return 距离（厘米）
 */
int sr04_measure(sr04_num_t num)
{
    switch (num)
    {
    case SR04_NUM1:
        return sr04_read(SR041_TRIG_PIN, SR041_ECHO_PIN);

    case SR04_NUM2:
        return sr04_read(SR042_TRIG_PIN, SR042_ECHO_PIN);

    case SR04_NUM3:
        return sr04_read(SR043_TRIG_PIN, SR043_ECHO_PIN);

    case SR04_NUM4:
        return sr04_read(SR044_TRIG_PIN, SR044_ECHO_PIN);

    default:
        return -1;
    }
}

int test_sr04(void)
{
    if (sr04_measure(SR04_NUM1) < 0)
    {
        LOG_E("test sr04 fail!");
        return -1;
    }
    else
    {
        LOG_I("distance: %d", sr04_measure(SR04_NUM1));
        return 0;
    }
}
MSH_CMD_EXPORT(test_sr04, test sr04);

int sr04_init(void)
{
    rt_pin_mode(SR041_TRIG_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(SR041_ECHO_PIN, PIN_MODE_INPUT_PULLDOWN);
    rt_pin_mode(SR042_TRIG_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(SR042_ECHO_PIN, PIN_MODE_INPUT_PULLDOWN);
    rt_pin_mode(SR043_TRIG_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(SR043_ECHO_PIN, PIN_MODE_INPUT_PULLDOWN);
    rt_pin_mode(SR044_TRIG_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(SR044_ECHO_PIN, PIN_MODE_INPUT_PULLDOWN);
    MX_TIM2_Init();

    return 0;
}
INIT_BOARD_EXPORT(sr04_init);
